package handler

import (
	"github.com/APP/internal/service/system_service"
	"github.com/APP/pkg/response"
	"strconv"

	"github.com/APP/internal/models"
	"github.com/APP/internal/utils"
	"github.com/gin-gonic/gin"
)

type AuthHandler struct {
	userService system_service.UserService
	jwtService  system_service.JwtService
	logService  system_service.LogService
}

func NewAuthHandler() *AuthHandler {
	return &AuthHandler{
		userService: system_service.UserService{},
		jwtService:  system_service.JwtService{},
	}
}

// LoginRequest 登录请求结构
type LoginRequest struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

// RegisterRequest 注册请求结构
type RegisterRequest struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
	Email    string `json:"email"`
	Nickname string `json:"nickname"`
}

// ChangePasswordRequest 修改密码请求结构
type ChangePasswordRequest struct {
	OldPassword string `json:"old_password" binding:"required"`
	NewPassword string `json:"new_password" binding:"required"`
}

// LoginResponse 登录响应结构
type LoginResponse struct {
	User      *models.User `json:"user"`
	Token     string       `json:"accessToken"`
	ExpiresAt int64        `json:"expires_at"`
}

// Login 用户登录
func (h *AuthHandler) Login(c *gin.Context) {
	var req LoginRequest

	// 1. 从请求中解析JSON数据绑定到 LoginRequest 结构体
	if err := c.ShouldBindJSON(&req); err != nil {
		code.Respond(c, code.ParamError.WithError(err), nil)
		return
	}

	// 2. 调用 userService 的 Login 方法，验证用户名和密码
	user, err := h.userService.Login(req.Username, req.Password)
	if err != nil {
		code.Respond(c, code.ServerError.WithInfo("登录失败").WithError(err), nil)
		go func() {
			h.logService.LogLoginAttempt(c, req.Username, 2, "")
		}()
		return
	}

	// 3. 创建 JWT 对象并生成 claims（JWT负载数据）
	j := utils.NewJWT()
	claims := j.CreateClaims(utils.BaseClaims{
		UUID:     strconv.Itoa(int(user.ID)),
		ID:       user.ID,
		Username: user.Username,
		NickName: user.Nickname,
	})

	// 4. 根据 claims 生成 token 字符串
	token, err := j.CreateToken(claims)
	if err != nil {
		code.Respond(c, code.ServerError.WithInfo("生成token失败").WithError(err), nil)
		return
	}

	// 5. （可选）将 token 存入 Redis 中，用于单点登录控制
	if err = h.jwtService.SetRedisJWT(token, user.Username); err != nil {
		code.Respond(c, code.ServerError.WithInfo("设置登录状态失败").WithError(err), nil)
		return
	}

	// 记录登录成功日志
	go func() {
		h.logService.LogLoginAttempt(c, req.Username, 1, "")
	}()

	// 6. 为了安全，把密码字段清空
	user.Password = ""

	// 7. 构造响应数据，返回用户信息、token、过期时间
	response := LoginResponse{
		User:      user,
		Token:     token,
		ExpiresAt: claims.ExpiresAt.Unix(), // 以秒为单位的过期时间戳
	}

	// 8. 返回成功响应
	code.Respond(c, code.Success, response)
}

// Register 用户注册
func (h *AuthHandler) Register(c *gin.Context) {
	var req RegisterRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		code.Respond(c, code.ParamError.WithError(err), nil)
		return
	}

	user := &models.User{
		Username: req.Username,
		Password: req.Password,
		Email:    req.Email,
		Nickname: req.Nickname,
		Status:   1,
	}

	createdUser, err := h.userService.Register(user)
	if err != nil {
		code.Respond(c, code.ServerError.WithInfo("注册失败").WithError(err), nil)
		return
	}

	// 清空密码字段
	createdUser.Password = ""
	code.Respond(c, code.Success, createdUser)
}

// Logout 用户登出
func (h *AuthHandler) Logout(c *gin.Context) {
	token := c.Request.Header.Get("x-token")
	if token == "" {
		token = c.Request.Header.Get("token")
	}
	if token == "" {
		authHeader := c.Request.Header.Get("Authorization")
		if authHeader != "" {
			token = authHeader[7:] // 去掉 "Bearer " 前缀
		}
	}

	if token != "" {
		// 将token加入黑名单
		jwtBlacklist := models.JwtBlacklist{Jwt: token}
		if err := h.jwtService.JsonInBlacklist(jwtBlacklist); err != nil {
			code.Respond(c, code.ServerError.WithInfo("登出失败").WithError(err), nil)
			return
		}
	}

	code.Respond(c, code.Success, "")
}

// GetUserInfo 获取用户信息
func (h *AuthHandler) GetUserInfo(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		code.Respond(c, code.ServerError.WithInfo("获取用户信息失败"), nil)
		return
	}

	customClaims := claims.(*utils.CustomClaims)
	user, err := h.userService.GetUserInfo(customClaims.BaseClaims.ID)
	if err != nil {
		code.Respond(c, code.ServerError.WithInfo("获取用户信息失败").WithError(err), nil)
		return
	}

	// 清空密码字段
	user.Password = ""
	user.Roles[0].Name = "super"
	code.Respond(c, code.Success, user)
}

// ChangePassword 修改密码
func (h *AuthHandler) ChangePassword(c *gin.Context) {
	var req ChangePasswordRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		code.Respond(c, code.ParamError, nil)
		return
	}

	claims, exists := c.Get("claims")
	if !exists {
		code.Respond(c, code.ServerError.WithInfo("获取用户信息失败"), nil)
		return
	}

	customClaims := claims.(*utils.CustomClaims)
	err := h.userService.ChangePassword(customClaims.BaseClaims.ID, req.OldPassword, req.NewPassword)
	if err != nil {
		code.Respond(c, code.ServerError.WithInfo("修改密码失败").WithError(err), nil)
		return
	}
	code.Respond(c, code.Success, "密码修改成功")
}

//给用户绑定角色
